/**
 * @file bme68x_defs.h
 * @brief Sensor driver for BME68x sensor.
 *
 * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license     The MIT License (MIT)
 * @author [GDuang](yonglei.ren@dfrobot.com)
 * @version  V1.0
 * @date  2024-04-25
 * @url https://github.com/DFRobot/DFRobot_BME68x
 */

#ifndef BME68X_DEFS_H_
#define BME68X_DEFS_H_

/********************************************************/
/* header includes */
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/kernel.h>
#else
#include <stdint.h>
#include <stddef.h>
#endif

/******************************************************************************/
/*! @name		Common macros					      */
/******************************************************************************/

#if !defined(UINT8_C) && !defined(INT8_C)
#define INT8_C(x)       (x)
#define UINT8_C(x)      (x)
#endif

#if !defined(UINT16_C) && !defined(INT16_C)
#define INT16_C(x)      (x)
#define UINT16_C(x)     (x)
#endif

#if !defined(INT32_C) && !defined(UINT32_C)
#define INT32_C(x)      (x)
#define UINT32_C(x)     (x)
#endif

#if !defined(INT64_C) && !defined(UINT64_C)
#define INT64_C(x)      (x)
#define UINT64_C(x)     (x)
#endif

/**@}*/

/**\name C standard macros */
#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *) 0)
#endif
#endif

#define UNUSED(x) (void)(x)

/** BME68X General config */
#define BME68X_POLL_PERIOD_MS		UINT8_C(10)

/** BME68X I2C addresses */
#define BME68X_I2C_ADDR_PRIMARY		UINT8_C(0x76)
#define BME68X_I2C_ADDR_SECONDARY	UINT8_C(0x77)

/** BME68X unique chip identifier */
#define BME68X_CHIP_ID  UINT8_C(0x61)

/** BME68X coefficients related defines */
#define BME68X_COEFF_SIZE		UINT8_C(0x41)
#define BME68X_COEFF_ADDR1_LEN		UINT8_C(25)
#define BME68X_COEFF_ADDR2_LEN		UINT8_C(16)

/** BME68X field_x related defines */
#define BME68X_FIELD_LENGTH		UINT8_C(15)
#define BME68X_FIELD_ADDR_OFFSET	UINT8_C(17)

/** Soft reset command */
#define BME68X_SOFT_RESET_CMD   UINT8_C(0xb6)

/** Error code definitions */
#define BME68X_OK		INT8_C(0)
/* Errors */
#define BME68X_E_NULL_PTR		    INT8_C(-1)
#define BME68X_E_COM_FAIL		    INT8_C(-2)
#define BME68X_E_DEV_NOT_FOUND		INT8_C(-3)
#define BME68X_E_INVALID_LENGTH		INT8_C(-4)

/* Warnings */
#define BME68X_W_DEFINE_PWR_MODE	INT8_C(1)
#define BME68X_W_NO_NEW_DATA        INT8_C(2)

/* Info's */
#define BME68X_I_MIN_CORRECTION		UINT8_C(1)
#define BME68X_I_MAX_CORRECTION		UINT8_C(2)

/** Register map */
/** Other coefficient's address */
#define BME68X_ADDR_RES_HEAT_VAL_ADDR	UINT8_C(0x00)
#define BME68X_ADDR_RES_HEAT_RANGE_ADDR	UINT8_C(0x02)
#define BME68X_ADDR_RANGE_SW_ERR_ADDR	UINT8_C(0x04)
#define BME68X_ADDR_SENS_CONF_START	UINT8_C(0x5A)
#define BME68X_ADDR_GAS_CONF_START	UINT8_C(0x64)

/** Field settings */
#define BME68X_FIELD0_ADDR		UINT8_C(0x1d)

/** Heater settings */
#define BME68X_RES_HEAT0_ADDR		UINT8_C(0x5a)
#define BME68X_GAS_WAIT0_ADDR		UINT8_C(0x64)

/** Sensor configuration registers */
#define BME68X_CONF_HEAT_CTRL_ADDR		UINT8_C(0x70)
#define BME68X_CONF_ODR_RUN_GAS_NBC_ADDR	UINT8_C(0x71)
#define BME68X_CONF_OS_H_ADDR			UINT8_C(0x72)
#define BME68X_MEM_PAGE_ADDR			UINT8_C(0xf3)
#define BME68X_CONF_T_P_MODE_ADDR		UINT8_C(0x74)
#define BME68X_CONF_ODR_FILT_ADDR		UINT8_C(0x75)

/** Coefficient's address */
#define BME68X_COEFF_ADDR1	UINT8_C(0x89)
#define BME68X_COEFF_ADDR2	UINT8_C(0xe1)

/** Chip identifier */
#define BME68X_CHIP_ID_ADDR	UINT8_C(0xd0)

/* Variant ID Register */
#define BME68X_REG_VARIANT_ID       UINT8_C(0xf0)	
/* Low version Gas variant */
#define BME68X_VARIANT_GAS_LOWV      UINT8_C(0x00)	
/* High version Gas variant */
#define BME68X_VARIANT_GAS_HIGHV     UINT8_C(0x01)	

/** Soft reset register */
#define BME68X_SOFT_RESET_ADDR		UINT8_C(0xe0)

/** Heater control settings */
#define BME68X_ENABLE_HEATER		UINT8_C(0x00)
#define BME68X_DISABLE_HEATER		UINT8_C(0x08)

/** Gas measurement settings */
#define BME68X_DISABLE_GAS_MEAS		UINT8_C(0x00)
#define BME68X_ENABLE_GAS_MEAS		UINT8_C(0x01)

/** Over-sampling settings */
#define BME68X_OS_NONE		UINT8_C(0)
#define BME68X_OS_1X		UINT8_C(1)
#define BME68X_OS_2X		UINT8_C(2)
#define BME68X_OS_4X		UINT8_C(3)
#define BME68X_OS_8X		UINT8_C(4)
#define BME68X_OS_16X		UINT8_C(5)

/** IIR filter settings */
#define BME68X_FILTER_SIZE_0	UINT8_C(0)
#define BME68X_FILTER_SIZE_1	UINT8_C(1)
#define BME68X_FILTER_SIZE_3	UINT8_C(2)
#define BME68X_FILTER_SIZE_7	UINT8_C(3)
#define BME68X_FILTER_SIZE_15	UINT8_C(4)
#define BME68X_FILTER_SIZE_31	UINT8_C(5)
#define BME68X_FILTER_SIZE_63	UINT8_C(6)
#define BME68X_FILTER_SIZE_127	UINT8_C(7)

/** Power mode settings */
#define BME68X_SLEEP_MODE	UINT8_C(0)
#define BME68X_FORCED_MODE	UINT8_C(1)

/** Delay related macro declaration */
#define BME68X_RESET_PERIOD	UINT32_C(10)

/** SPI memory page settings */
#define BME68X_MEM_PAGE0	UINT8_C(0x10)
#define BME68X_MEM_PAGE1	UINT8_C(0x00)

/** Ambient humidity shift value for compensation */
#define BME68X_HUM_REG_SHIFT_VAL	UINT8_C(4)

/** Run gas enable and disable settings */
#define BME68X_RUN_GAS_DISABLE	UINT8_C(0)
#define BME68X_RUN_GAS_ENABLE	UINT8_C(1)

/** Buffer length macro declaration */
#define BME68X_TMP_BUFFER_LENGTH	UINT8_C(40)
#define BME68X_REG_BUFFER_LENGTH	UINT8_C(6)
#define BME68X_FIELD_DATA_LENGTH	UINT8_C(3)
#define BME68X_GAS_REG_BUF_LENGTH	UINT8_C(20)
#define BME68X_GAS_HEATER_PROF_LEN_MAX  UINT8_C(10)

/** Settings selector */
#define BME68X_OST_SEL			UINT16_C(1)
#define BME68X_OSP_SEL			UINT16_C(2)
#define BME68X_OSH_SEL			UINT16_C(4)
#define BME68X_GAS_MEAS_SEL		UINT16_C(8)
#define BME68X_FILTER_SEL		UINT16_C(16)
#define BME68X_HCNTRL_SEL		UINT16_C(32)
#define BME68X_RUN_GAS_SEL		UINT16_C(64)
#define BME68X_NBCONV_SEL		UINT16_C(128)
#define BME68X_GAS_SENSOR_SEL		(BME68X_GAS_MEAS_SEL | BME68X_RUN_GAS_SEL | BME68X_NBCONV_SEL)

/** Number of conversion settings*/
#define BME68X_NBCONV_MIN		UINT8_C(0)
#define BME68X_NBCONV_MAX		UINT8_C(10)

/** Mask definitions */
#define BME68X_GAS_MEAS_MSK	UINT8_C(0x30)
#define BME68X_NBCONV_MSK	UINT8_C(0X0F)
#define BME68X_FILTER_MSK	UINT8_C(0X1C)
#define BME68X_OST_MSK		UINT8_C(0XE0)
#define BME68X_OSP_MSK		UINT8_C(0X1C)
#define BME68X_OSH_MSK		UINT8_C(0X07)
#define BME68X_HCTRL_MSK	UINT8_C(0x08)
#define BME68X_RUN_GAS_LOWV_MSK		UINT8_C(0x10)	
#define BME68X_RUN_GAS_HIGHV_MSK	UINT8_C(0x20)	
#define BME68X_MODE_MSK		UINT8_C(0x03)
#define BME68X_RHRANGE_MSK	UINT8_C(0x30)
#define BME68X_RSERROR_MSK	UINT8_C(0xf0)
#define BME68X_NEW_DATA_MSK	UINT8_C(0x80)
#define BME68X_GAS_INDEX_MSK	UINT8_C(0x0f)
#define BME68X_GAS_RANGE_MSK	UINT8_C(0x0f)
#define BME68X_GASM_VALID_MSK	UINT8_C(0x20)
#define BME68X_HEAT_STAB_MSK	UINT8_C(0x10)
#define BME68X_MEM_PAGE_MSK	UINT8_C(0x10)
#define BME68X_SPI_RD_MSK	UINT8_C(0x80)
#define BME68X_SPI_WR_MSK	UINT8_C(0x7f)
#define	BME68X_BIT_H1_DATA_MSK	UINT8_C(0x0F)

/** Bit position definitions for sensor settings */
#define BME68X_GAS_MEAS_POS	UINT8_C(4)
#define BME68X_FILTER_POS	UINT8_C(2)
#define BME68X_OST_POS		UINT8_C(5)
#define BME68X_OSP_POS		UINT8_C(2)
#define BME68X_RUN_GAS_LOWV_POS		UINT8_C(4)	
#define BME68X_RUN_GAS_HIGHV_POS	UINT8_C(5) 	

/** Array Index to Field data mapping for Calibration Data*/
#define BME68X_T2_LSB_REG	(1)
#define BME68X_T2_MSB_REG	(2)
#define BME68X_T3_REG		(3)
#define BME68X_P1_LSB_REG	(5)
#define BME68X_P1_MSB_REG	(6)
#define BME68X_P2_LSB_REG	(7)
#define BME68X_P2_MSB_REG	(8)
#define BME68X_P3_REG		(9)
#define BME68X_P4_LSB_REG	(11)
#define BME68X_P4_MSB_REG	(12)
#define BME68X_P5_LSB_REG	(13)
#define BME68X_P5_MSB_REG	(14)
#define BME68X_P7_REG		(15)
#define BME68X_P6_REG		(16)
#define BME68X_P8_LSB_REG	(19)
#define BME68X_P8_MSB_REG	(20)
#define BME68X_P9_LSB_REG	(21)
#define BME68X_P9_MSB_REG	(22)
#define BME68X_P10_REG		(23)
#define BME68X_H2_MSB_REG	(25)
#define BME68X_H2_LSB_REG	(26)
#define BME68X_H1_LSB_REG	(26)
#define BME68X_H1_MSB_REG	(27)
#define BME68X_H3_REG		(28)
#define BME68X_H4_REG		(29)
#define BME68X_H5_REG		(30)
#define BME68X_H6_REG		(31)
#define BME68X_H7_REG		(32)
#define BME68X_T1_LSB_REG	(33)
#define BME68X_T1_MSB_REG	(34)
#define BME68X_GH2_LSB_REG	(35)
#define BME68X_GH2_MSB_REG	(36)
#define BME68X_GH1_REG		(37)
#define BME68X_GH3_REG		(38)

/** BME68X register buffer index settings*/
#define BME68X_REG_FILTER_INDEX		UINT8_C(5)
#define BME68X_REG_TEMP_INDEX		UINT8_C(4)
#define BME68X_REG_PRES_INDEX		UINT8_C(4)
#define BME68X_REG_HUM_INDEX		UINT8_C(2)
#define BME68X_REG_NBCONV_INDEX		UINT8_C(1)
#define BME68X_REG_RUN_GAS_INDEX	UINT8_C(1)
#define BME68X_REG_HCTRL_INDEX		UINT8_C(0)

/** Macro to combine two 8 bit data's to form a 16 bit data */
#define BME68X_CONCAT_BYTES(msb, lsb)	(((uint16_t)msb << 8) | (uint16_t)lsb)

/** Macro to SET and GET BITS of a register */
#define BME68X_SET_BITS(reg_data, bitname, data) \
		((reg_data & ~(bitname##_MSK)) | \
		((data << bitname##_POS) & bitname##_MSK))
#define BME68X_GET_BITS(reg_data, bitname)	((reg_data & (bitname##_MSK)) >> \
	(bitname##_POS))

/** Macro variant to handle the bitname position if it is zero */
#define BME68X_SET_BITS_POS_0(reg_data, bitname, data) \
				((reg_data & ~(bitname##_MSK)) | \
				(data & bitname##_MSK))
#define BME68X_GET_BITS_POS_0(reg_data, bitname)  (reg_data & (bitname##_MSK))

/**
 * @fn bme68x_com_fptr_t
 * @brief Generic communication function pointer
 * @param dev_id: Place holder to store the id of the device structure
 * @n                 Can be used to store the index of the Chip select or
 * @n                 I2C address of the device.
 * @param reg_addr:	Used to select the register the where data needs to
 *                      be read from or written to.
 * @param data: Data array to read/write
 * @param len: Length of the data array
 * @return int8_t type
 */
typedef int8_t (*bme68x_com_fptr_t)(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);

/**
 * @fn bme68x_delay_fptr_t
 * @brief Delay function pointer
 * @param[in] period: Time period in milliseconds
 */
typedef void (*bme68x_delay_fptr_t)(uint32_t period);

/**
 * @enum bme68x_intf
 * @brief Interface selection Enumerations
 */
enum bme68x_intf {
	
	BME68X_SPI_INTF,
	BME68X_I2C_INTF /**< I2C interface */
};

/**
 * @struct bme68x_field_data
 * @brief Sensor field data structure
 */
struct	bme68x_field_data {
	uint8_t status;          /**< Contains new_data, gasm_valid & heat_stab */
	uint8_t gas_index;       /**< The index of the heater profile used */
	uint8_t meas_index;      /**< Measurement index to track order */
	int16_t temperature;     /**< Temperature in degree celsius x100 */
	uint32_t pressure;       /**< Pressure in Pascal */
	uint32_t humidity;       /**< Humidity in % relative humidity x1000 */
	uint32_t gas_resistance; /**< Gas resistance in Ohms */
};

/**
 * @struct bme68x_calib_data
 * @brief Structure to hold the Calibration data
 */
struct	bme68x_calib_data {
	
	uint16_t par_h1; /**< Variable to store calibrated humidity data */
	uint16_t par_h2; /**< Variable to store calibrated humidity data */
	int8_t par_h3;   /**< Variable to store calibrated humidity data */
	int8_t par_h4;   /**< Variable to store calibrated humidity data */
	int8_t par_h5;   /**< Variable to store calibrated humidity data */
	uint8_t par_h6;  /**< Variable to store calibrated humidity data */
	int8_t par_h7;   /**< Variable to store calibrated humidity data */
	int8_t par_gh1;  /**< Variable to store calibrated gas data */
	int16_t par_gh2; /**< Variable to store calibrated gas data */
	int8_t par_gh3;  /**< Variable to store calibrated gas data */
	uint16_t par_t1; /**< Variable to store calibrated temperature data */
	int16_t par_t2;  /**< Variable to store calibrated temperature data */
	int8_t par_t3;   /**< Variable to store calibrated temperature data */
	uint16_t par_p1; /**< Variable to store calibrated pressure data */
	int16_t par_p2;  /**< Variable to store calibrated pressure data */
	int8_t par_p3;   /**< Variable to store calibrated pressure data */
	int16_t par_p4;  /**< Variable to store calibrated pressure data */
	int16_t par_p5;  /**< Variable to store calibrated pressure data */
	int8_t par_p6;   /**< Variable to store calibrated pressure data */
	int8_t par_p7;   /**< Variable to store calibrated pressure data */
	int16_t par_p8;  /**< Variable to store calibrated pressure data */
	int16_t par_p9;  /**< Variable to store calibrated pressure data */
	uint8_t par_p10; /**< Variable to store calibrated pressure data */
	int32_t t_fine;  /**< Variable to store t_fine size */
	uint8_t res_heat_range;/**< Variable to store heater resistance range */
	int8_t res_heat_val;   /**< Variable to store heater resistance value */
	int8_t range_sw_err;   /**< Variable to store error range */
};

/**
 * @struct bme68x_tph_sett
 * @brief BME68X sensor settings structure which comprises of ODR,
 * over-sampling and filter settings.
 */
struct	bme68x_tph_sett {
	uint8_t os_hum; /**< Humidity oversampling */
	uint8_t os_temp;/**< Temperature oversampling */
	uint8_t os_pres;/**< Pressure oversampling */
	uint8_t filter; /**< Filter coefficient */
};

/**
 * @struct bme68x_gas_sett
 * @brief BME68X gas sensor which comprises of gas settings
 *  and status parameters
 */
struct	bme68x_gas_sett {
	uint8_t nb_conv;    /**< Variable to store nb conversion */
	uint8_t heatr_ctrl; /**< Variable to store heater control */
	uint8_t run_gas;    /**< Run gas enable value */
	uint16_t heatr_temp;/**< Pointer to store heater temperature */
	uint16_t heatr_dur; /**< Pointer to store duration profile */
};

/**
 * @struct bme68x_dev
 * @brief BME68X device structure
 */
struct	bme68x_dev {

    /*!
     *             Variant id
     * ----------------------------------------
     *     Value   |           Variant
     * ----------------------------------------
     *      0      |   BME68X_VARIANT_GAS_LOWV
     *      1      |   BME68X_VARIANT_GAS_HIGHV
     * ----------------------------------------
     */
    uint8_t variant_id;			 	 /**< variant ID: bme680(LOW)/bme688(HIGH)*/															 
	uint8_t chip_id;                 /**< Chip Id */
	uint8_t dev_id;                  /**< Device Id */
	enum bme68x_intf intf;           /**< SPI/I2C interface */
	uint8_t mem_page;                /**< Memory page used */
	int8_t amb_temp;                 /**< Ambient temperature in Degree C*/
	struct bme68x_calib_data calib;  /**< Sensor calibration data */
	struct bme68x_tph_sett tph_sett; /**< Sensor settings */
	struct bme68x_gas_sett gas_sett; /**< Gas Sensor settings */
	uint8_t power_mode;              /**< Sensor power modes */
	uint8_t new_fields;              /**< New sensor fields */
	uint8_t info_msg;                /**< Store the info messages */
	bme68x_com_fptr_t read;          /**< Burst read structure */
	bme68x_com_fptr_t write;         /**< Burst write structure */
	bme68x_delay_fptr_t delay_ms;    /**< Delay in ms */
	int8_t com_rslt;                 /**< Communication function result */
};



#endif 
